package com.qcby.handler;

import com.google.gson.Gson;
import com.qcby.entity.*;
import com.qcby.service.DeepSeekService;
import com.qcby.service.MessageService;
import com.qcby.util.GsonUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.*;

import static com.qcby.interceptor.ChatInterceptor.*;

@Component
public class ChatHandler implements WebSocketHandler {
    @Autowired
    private DeepSeekService deepSeekService;
    @Autowired
    private MessageService messageService;
//    public static List<Student> studentList = new ArrayList<>();
//    public static List<Teacher> teacherList = new ArrayList<>();
    public static final Map<String, WebSocketSession> USER_SOCKETSESSION_MAP = new HashMap<String, WebSocketSession>();
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        boolean isTeacher =true;
        //群发消息告知大家
        Message msg = new Message();
        List<Message> messageList= messageService.findSystemAllMessage(msg);
        Collections.reverse(messageList);
        System.out.println("全部消息"+messageList);
        msg.setData(messageList);
        System.out.println(msg.getData());
        msg.setType("system");
//        如果上线的是学生
        if(userList.get(userList.size()-1) instanceof Student){
            Student student = (Student) userList.get(userList.size()-1);
            USER_SOCKETSESSION_MAP.put(student.getSno(), session);
            msg.setText("【学生"+student.getName()+"】上线了！");
        }else{
//            上线的是老师
            Teacher teacher = (Teacher) userList.get(userList.size()-1);
            USER_SOCKETSESSION_MAP.put(teacher.getWorkNumber(), session);
            msg.setText("【老师"+teacher.getName()+"】上线了！");
        }
        msg.setUserList(new ArrayList<>(userList));
        System.out.println("用户列表:"+userList);
        //将数据转换成json
        Gson gson = new Gson();
        String json = gson.toJson(msg);
        if(session.getUri().toString().contains("ai")){
            sendMessageToUser(session,new TextMessage(json));
        }else {
            //群发消息
            sendMessageToAll(new TextMessage(json));
        }
    }
    private void sendMessageToAll(WebSocketMessage<?> message) throws IOException {
        //获取到所有在线用户的SocketSession对象
        Set<Map.Entry<String, WebSocketSession>> entrySet = USER_SOCKETSESSION_MAP.entrySet();  //去重
        for (Map.Entry<String, WebSocketSession> entry : entrySet) {
            //某用户的WebSocketSession
            final WebSocketSession webSocketSession = entry.getValue();
            //判断连接是否仍然打开的
            if(webSocketSession.isOpen()){
                if (webSocketSession.isOpen()) {
                    webSocketSession.sendMessage(message);
                }
            }
        }
    }
    private void sendMessageToUser(WebSocketSession webSocketSession , TextMessage message) throws IOException{
        //获取到要接收消息的用户的session
        if (webSocketSession != null && webSocketSession.isOpen()) {
            //发送消息
            webSocketSession.sendMessage(message);
        }
    }
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        //如果消息没有任何内容，则直接返回
        if(message.getPayloadLength()==0) {return;}
        System.out.println("消息（可存数据库作为历史记录）:"+message.getPayload().toString());
        //反序列化服务端收到的json消息
        Message msg = GsonUtils.fromJson(message.getPayload().toString(), Message.class);
        System.out.println(msg);
        if(msg.getType().equals("message")){
//            发送群消息和单个消息
            messageService.addMessage(msg);
            Message sendMsg = new Message();
            sendMsg.setFromName(msg.getFromName());
            sendMsg.setText(msg.getText());
            sendMsg.setTo(msg.getTo());
            sendMsg.setType("message");
            sendMsg.setToicon(msg.getFromicon());
            sendMsg.setFromicon(msg.getFromicon());
            sendMsg.setFileSize(msg.getFileSize());
            sendMsg.setFileName(msg.getFileName());
            sendMsg.setFileType(msg.getFileType());
            if(msg.getTo().equals("AI")){
                sendMsg.setBtnShow(true);
            }
            Gson gson = new Gson();
            String json = gson.toJson(sendMsg);
            sendMessageToAll(new TextMessage(json));
            if(msg.getTo().equals("AI")){
                String res = deepSeekService.getJson(msg.getText());
                JSONObject jsonObject = new JSONObject(res);
                res = jsonObject.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content");
                sendMsg.setFromName("AI");
                sendMsg.setText(res);
                sendMsg.setTo(msg.getFromName());
                sendMsg.setType("message");
                sendMsg.setToicon(msg.getFromicon());
                sendMsg.setFromicon(msg.getToicon());
                sendMsg.setFileSize(msg.getFileSize());
                sendMsg.setFileName(msg.getFileName());
                sendMsg.setFileType(msg.getFileType());
                sendMsg.setBtnShow(false);
                String json1 = gson.toJson(sendMsg);
                System.out.println(sendMsg);
                messageService.addMessage(sendMsg);
                sendMessageToAll(new TextMessage(json1));
            }
        }else if(msg.getType().equals("ChangeSingle")){
//            切换点人的视角
            Message checkMsg = new Message();
            checkMsg.setFromName(msg.getFromName());
            checkMsg.setFromicon(msg.getFromicon());
            checkMsg.setToicon(msg.getToicon());
            checkMsg.setTo(msg.getTo());
            checkMsg.setPage(msg.getPage());
            checkMsg.setPageSize(msg.getPageSize());
            List<Message> messageList = new ArrayList<>();
//发送群聊消息
            if(checkMsg.getTo().equals("群聊")){
                messageList = messageService.findSystemAllMessage(checkMsg);
            }else{
//                发送个人消息
                messageList=messageService.findSingleMessage(checkMsg);
            }
            Collections.reverse(messageList);
            Message sendMsg = new Message();
            sendMsg.setData(messageList);
            sendMsg.setType("ChangeSingle");
            sendMsg.setToicon(msg.getToicon());
            sendMsg.setTo(msg.getTo());
            sendMsg.setFromicon(msg.getFromicon());
            sendMsg.setFromName(msg.getFromName());
            sendMsg.setUserList(userList);
            Gson gson = GsonUtils.getGson();
            String json = gson.toJson(sendMsg);
            sendMessageToUser(session,new TextMessage(json));
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        // 记录日志，准备关闭连接
        System.out.println("Websocket异常断开:" + session.getId() + "已经关闭");
        //一旦发生异常，强制用户下线，关闭session
        if (session.isOpen()) {
            session.close();
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        //群发消息告诉大家
        Message msg = new Message();
        msg.setType("system");
//        记录清空
        msg.setUserList(new ArrayList<>());
        Set<Map.Entry<String, WebSocketSession>> entrySet = USER_SOCKETSESSION_MAP.entrySet();
        // 记录日志，准备关闭连接
        System.out.println("Websocket正常断开:" + session.getId() + "已经关闭");
        if(session.getAttributes().get("teacher") != null && teacherList.contains((Teacher) session.getAttributes().get("teacher"))){
            Teacher teacher =(Teacher) session.getAttributes().get("teacher");
            //并查找出在线用户的WebSocketSession（会话），将其移除（不再对其发消息了。。）
            System.out.println(teacher);
            for (Map.Entry<String, WebSocketSession> entry : entrySet) {
                System.out.println(entry);
                if(entry.getKey().equals(teacher.getWorkNumber())){
                    //群发消息告知大家
                    msg.setText("万众瞩目的【"+teacher.getName()+"】已经有事先走了，大家继续聊...");
                    //清除在线会话
                    USER_SOCKETSESSION_MAP.remove(entry.getKey());
                    //记录日志：
                    System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
                    break;
                }
            }
            teacherList.remove(teacher);
        }else{
            Student student =(Student) session.getAttributes().get("student");
            for (Map.Entry<String, WebSocketSession> entry : entrySet) {
                if(entry.getKey().equals(student.getSno())){
                    //群发消息告知大家
                    msg.setText("万众瞩目的【"+student.getName()+"】已经有事先走了，大家继续聊...");
                    //清除在线会话
                    USER_SOCKETSESSION_MAP.remove(entry.getKey());
                    //记录日志：
                    System.out.println("Socket会话已经移除:用户ID" + entry.getKey());
                    break;
                }
            }
            studentList.remove(student);
        }
//        //获取异常的用户的会话中的用户编号
//        User loginUser=(User) session.getAttributes().get("loginUser");
        userList = new ArrayList<>();
        //将最新的所有的在线人列表放入消息对象的list集合中，用于页面显示
        for (Map.Entry<String, WebSocketSession> entry : entrySet) {
            if(entry.getValue().getAttributes().get("teacher")!=null){
                Teacher teacher1 = (Teacher) entry.getValue().getAttributes().get("teacher");
                userList.add(teacher1);
            }else{
                Student student1 = (Student) entry.getValue().getAttributes().get("student");
                userList.add(student1);
            }
        }
        msg.setUserList(new ArrayList<>(userList));
        TextMessage message = new TextMessage(GsonUtils.toJson(msg));
        if(session.getUri().toString().contains("ai")){
            sendMessageToUser(session,message);
        }else {
            //群发消息
            sendMessageToAll(message);
        }
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}
